package com.yumeng.framework.auth.shiro.realm;

import com.yumeng.common.helper.AssertHelper;
import com.yumeng.common.utils.SpringUtils;
import com.yumeng.common.auth.BaseAuthInfo;
import com.yumeng.framework.auth.service.auth.RemoteAuthService;
import com.yumeng.framework.auth.shiro.token.RemoteAuthToken;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

/**
 * 远程用户名密码认证
 *
 * @author wxd
 * @date 2022/9/29 15:53
 */
@Slf4j
public class RemoteAuthRealm extends AuthorizingRealm {

    public static final String DEFAULT_BEAN_NAME = "remoteAuthRealm";

    private volatile RemoteAuthService authService;
    private String authServiceName = "";

    public RemoteAuthRealm(String authServiceName){
        this.authServiceName = authServiceName;
        setName("remoteUsernameRealm");
        AssertHelper.assertNotBlank(this.authServiceName, "authServiceName is blank");
    }

    public RemoteAuthService getAuthService() {
        if (this.authService == null){
            synchronized(RemoteAuthRealm.class){
                if (this.authService == null){
                    this.authService = SpringUtils.getBean(this.authServiceName);
                    AssertHelper.assertNotNull(this.authService, "authService is null");
                }
            }
        }
        return this.authService;
    }

    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof RemoteAuthToken;
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        log.debug("RemoteAuthRealm::授权");//可能执行多次 权限判断次数多少，就会执行多少次 如，接口的权限为 demo:user:add,root  则会调用两次

/*        Subject subject = SecurityUtils.getSubject();
        AuthInfo authInfo = (AuthInfo)subject.getPrincipal();*///直接调用subject.getPrincipal获取PrimaryPrincipal（即所谓的第一个）

        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        BaseAuthInfo authInfo = (BaseAuthInfo)getAvailablePrincipal(principals);
        //TODO 权限待完善
/*        if (!authInfo.getSuperAdmin()){
            RolePermPkg pkg = getAuthService().getRoleAndPermissions(authInfo.getIdentityId());
            // 角色加入AuthorizationInfo认证对象
            authorizationInfo.setRoles(pkg.getRoles());
            // 权限加入AuthorizationInfo认证对象
            authorizationInfo.setStringPermissions(pkg.getPerms());
        }else{
            authorizationInfo.addRole("admin");
            authorizationInfo.addStringPermission("*:*:*");
        }*/
        return authorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        log.debug("RemoteAuthRealm::认证");

        //1.判断用户名  token中的用户信息是登录时候传进来的
        RemoteAuthToken upToken = (RemoteAuthToken)token;
        BaseAuthInfo authInfo = getAuthService().remoteAuth(upToken.getAccount(), upToken.getPassword());

        if(authInfo==null){
            throw new AccountException("远程认证失败");
        }
        //TODO 状态判断完善
        if (!authInfo.isEnabled()){
            //账号已停用
            throw new DisabledAccountException("账号已停用");
        }

        String salt = authInfo.getSalt();
        if (StringUtils.isBlank(salt)){
            throw new AccountException("盐值缺失");
        }
        //远程认证，密码已经在remoteAuth方法中远程系统认证了，密码验证直接通过
        return new SimpleAuthenticationInfo(authInfo, authInfo.getCredentials(), getName());//  new SerializableByteSource(salt) ByteSource.Util.bytes(salt)
    }

}
